<?php
/* $Id$ */
/*
    firewall_nat_out_edit.php
    Copyright (C) 2004 Scott Ullrich
    All rights reserved.

    originally part of m0n0wall (http://m0n0.ch/wall)
    Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE.
*/

##|+PRIV
##|*IDENT=page-firewall-nat-outbound-edit
##|*NAME=Firewall: NAT: Outbound: Edit page
##|*DESCR=Allow access to the 'Firewall: NAT: Outbound: Edit' page.
##|*MATCH=firewall_nat_out_edit.php*
##|-PRIV


require("guiconfig.inc");

if (!is_array($config['nat']['advancedoutbound']['rule']))
	$config['nat']['advancedoutbound']['rule'] = array();

$a_out = &$config['nat']['advancedoutbound']['rule'];
//nat_out_rules_sort();

$id = $_GET['id'];
if (isset($_POST['id']))
	$id = $_POST['id'];

if (isset($_GET['dup']))  {
	$id  =  $_GET['dup'];
	$after  =  $_GET['dup'];
}

if (isset($id) && $a_out[$id]) {
    list($pconfig['source'],$pconfig['source_subnet']) = explode('/', $a_out[$id]['source']['network']);
    $pconfig['sourceport'] = $a_out[$id]['sourceport'];
    address_to_pconfig($a_out[$id]['destination'], $pconfig['destination'],
	   $pconfig['destination_subnet'], $pconfig['destination_not'],
	   $none, $none);
    $pconfig['dstport'] = $a_out[$id]['dstport'];
    $pconfig['natport'] = $a_out[$id]['natport'];
    $pconfig['target'] = $a_out[$id]['target'];
    $pconfig['interface'] = $a_out[$id]['interface'];
	if (!$pconfig['interface'])
		$pconfig['interface'] = "wan";
    $pconfig['descr'] = $a_out[$id]['descr'];
    $pconfig['nonat'] = $a_out[$id]['nonat'];
    $pconfig['staticnatport'] = isset($a_out[$id]['staticnatport']);
    $pconfig['nosync'] = isset($a_out[$id]['nosync']);
} else {
    $pconfig['source_subnet'] = 24;
    $pconfig['destination'] = "any";
    $pconfig['destination_subnet'] = 24;
	$pconfig['interface'] = "wan";
}

if (isset($_GET['dup']))
        unset($id);

if ($_POST) {

    if ($_POST['destination_type'] == "any") {
        $_POST['destination'] = "any";
        $_POST['destination_subnet'] = 24;
    }
    if ($_POST['source_type'] == "any") {
        $_POST['source'] = "any";
        $_POST['source_subnet'] = 24;
    }

    unset($input_errors);
    $pconfig = $_POST;

    /* input validation */
    $reqdfields = explode(" ", "interface source source_subnet destination destination_subnet");
    $reqdfieldsn = explode(",", "接口,源地址,源地址子网掩码,目的地址,目的地址子网掩码");

    do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);

	if($_POST['sourceport'] <> "" and !is_numericint($_POST['sourceport']))
		$input_errors[] = "请输入有效的源端口。";

	if($_POST['dstport'] <> "" and !is_numericint($_POST['dstport']))
		$input_errors[] = "请输入有效的目的端口。";

	if($_POST['natport'] <> "" and !is_numericint($_POST['natport']))
		$input_errors[] = "请输入有效的NAT端口。";

    if ($_POST['source_type'] != "any") {
        if ($_POST['source'] && !is_ipaddr($_POST['source']) && $_POST['source'] <> "any") {
            $input_errors[] = "请输入有效的源地址。";
        }
        if ($_POST['source_subnet'] && !is_numericint($_POST['source_subnet'])) {
            $input_errors[] = "请输入有效的源地址子网掩码。";
        }
    }
    if ($_POST['destination_type'] != "any") {
        if ($_POST['destination'] && !is_ipaddr($_POST['destination'])) {
            $input_errors[] = "请输入有效的目的地址。";
        }
        if ($_POST['destination_subnet'] && !is_numericint($_POST['destination_subnet'])) {
            $input_errors[] = "请输入有效的目的地址子网掩码。";
        }
    }
    if ($_POST['destination_type'] == "any") {
	if ($_POST['destination_not'])
            $input_errors[] = "any取反是无效的。";
    }

    if ($_POST['target'] && !is_ipaddr($_POST['target'])) {
        $input_errors[] = "请输入有效的目的地址。";
    }

    /* if user has selected any as source, set it here */
    if($_POST['source_type'] == "any") {
	$osn = "any";
    } else {
	$osn = gen_subnet($_POST['source'], $_POST['source_subnet']) . "/" . $_POST['source_subnet'];
    }

    /* check for existing entries */
    if ($_POST['destination_type'] == "any")
        $ext = "any";
    else
        $ext = gen_subnet($_POST['destination'], $_POST['destination_subnet']) . "/"
            . $_POST['destination_subnet'];

	if ($_POST['target']) {
		/* check for clashes with 1:1 NAT (NAT Addresses is OK) */
		if (is_array($config['nat']['onetoone'])) {
			foreach ($config['nat']['onetoone'] as $natent) {
				if (check_subnets_overlap($_POST['target'], 32, $natent['external'], $natent['subnet'])) {
					$input_errors[] = "一条1:1 NAT映射规则目标IP地址重叠。";
					break;
				}
			}
		}
	}

    foreach ($a_out as $natent) {
        if (isset($id) && ($a_out[$id]) && ($a_out[$id] === $natent))
            continue;

		if (!$natent['interface'])
			$natent['interface'] == "wan";

		if (($natent['interface'] == $_POST['interface']) && ($natent['source']['network'] == $osn)) {
			if (isset($natent['destination']['not']) == isset($_POST['destination_not'])) {
				if ((isset($natent['destination']['any']) && ($ext == "any")) ||
						($natent['destination']['address'] == $ext)) {
					//$input_errors[] = "There is already an outbound NAT rule with the specified settings.";
					break;
				}
			}
		}
    }

    if (!$input_errors) {
        $natent = array();
        $natent['source']['network'] = $osn;
        $natent['sourceport'] = $_POST['sourceport'];
        $natent['descr'] = $_POST['descr'];
        $natent['target'] = $_POST['target'];
        $natent['interface'] = $_POST['interface'];

		/* static-port */
		if(isset($_POST['staticnatport']))
			$natent['staticnatport'] = true;
		else
			unset($natent['staticnatport']);

		/* if user has selected not nat, set it here */
		if(isset($_POST['nonat']))
			$natent['nonat'] = true;
		else
			unset($natent['nonat']);

        if ($ext == "any")
            $natent['destination']['any'] = true;
        else
            $natent['destination']['address'] = $ext;

        $natent['natport'] = $_POST['natport'];
        $natent['dstport'] = $_POST['dstport'];

		if($_POST['nosync'] == "yes")
			$natent['nosync'] = true;
		else
			unset($natent['nosync']);

        if (isset($_POST['destination_not']) && $ext != "any")
            $natent['destination']['not'] = true;

		if (isset($id) && $a_out[$id])
			$a_out[$id] = $natent;
		else {
			if (is_numeric($after))
				array_splice($a_out, $after+1, 0, array($natent));
			else
				$a_out[] = $natent;
		}

        touch($d_natconfdirty_path);

        write_config();

        header("Location: firewall_nat_out.php");
        exit;
    }
}

$pgtitle = array("防火墙","NAT管理","NAT规则","编辑");
$pgmenu = array('nat', '/firewall_nat_out.php');
$closehead = false;
include("head.inc");

?>

<script language="JavaScript">
<!--
function staticportchange() {
	if(document.iform.staticnatport.checked) {
		document.iform.natport.value = "";
		document.iform.natport.disabled = 1;
	} else {
		document.iform.natport.disabled = 0;
	}
}
function typesel_change() {
    switch (document.iform.destination_type.selectedIndex) {
        case 1: // network
            document.iform.destination.disabled = 0;
            document.iform.destination_subnet.disabled = 0;
            break;
        default:
            document.iform.destination.value = "";
            document.iform.destination.disabled = 1;
            document.iform.destination_subnet.value = "24";
            document.iform.destination_subnet.disabled = 1;
            break;
    }
}
function sourcesel_change() {
    switch (document.iform.source_type.selectedIndex) {
        case 1: // network
            document.iform.source.disabled = 0;
            document.iform.source_subnet.disabled = 0;
            break;
        default:
	    document.iform.source.value = "";
	    document.iform.sourceport.value = "";
            document.iform.source.disabled = 1;
            document.iform.source_subnet.value = "24";
            document.iform.source_subnet.disabled = 1;
            break;
    }
}
//-->
</script>
</head>

<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php include("fbegin.inc"); ?>
<?php if ($input_errors) print_input_errors($input_errors); ?>
            <form action="firewall_nat_out_edit.php" method="post" name="iform" id="iform">
              <table width="100%" border="0" cellpadding="6" cellspacing="1">
				<tr>
					<td colspan="2" valign="top" class="listtopic">高级NAT规则编辑</td>
				</tr>
	        <tr>
                  <td width="22%" valign="top" class="vncell">禁用NAT</td>
                  <td width="78%" class="vtable">
			<input type="checkbox" name="nonat"<?php if(isset($pconfig['nonat'])) echo " CHECKED"; ?>>
                     <span class="vexpl">选中该选项会使匹配该规则的数据停止NAT转换。
		     <br>提示：大多数情况下，您不需要该选项。</span></td>
                </tr>
	        <tr>
                  <td width="22%" valign="top" class="vncellreq">接口</td>
                  <td width="78%" class="vtable">
			<select name="interface" class="formselect">
				<?php
				$interfaces = get_configured_interface_with_descr(false, true);
				foreach ($interfaces as $iface => $ifacename): ?>
				<option value="<?=$iface;?>" <?php if ($iface == $pconfig['interface']) echo "selected"; ?>>
				<?=htmlspecialchars($ifacename);?>
				</option>
				<?php endforeach; ?>
			</select><br>
                     <span class="vexpl">选择规则应用的接口。<br>
                     提示：大多数情况您可能需要选择WAN。</span></td>
                </tr>
                <tr>
                  <td width="22%" valign="top" class="vncellreq">源地址</td>
                  <td width="78%" class="vtable">
                    <table border="0" cellspacing="1" cellpadding="1">
                      <tr>
		        <td>类型：&nbsp;&nbsp;</td>
			<td>
			    <select name="source_type" class="formselect" onChange="sourcesel_change()">
                              <option value="any" <?php if ($pconfig['source'] == "any") echo "selected"; ?>>所有</option>
                              <option value="network" <?php if ($pconfig['source'] != "any") echo "selected"; ?>>网段</option>
                            </select>
			</td></tr>
                        <td>地址：&nbsp;&nbsp;</td>
                        <td><input name="source" type="text" class="formfld unknown" id="source" size="20" value="<?=htmlspecialchars($pconfig['source']);?>">/<select name="source_subnet" class="formfld" id="source_subnet">
<?php for ($i = 32; $i >= 0; $i--): ?>
                          <option value="<?=$i;?>"<?php if ($i == $pconfig['source_subnet']) echo " selected"; ?>><?=$i;?></option>
<?php endfor; ?>
                          </select></td>
                      </tr>
                      <tr>
                        <td>&nbsp;</td>
                        <td><span class="vexpl">输入NAT转换的源地址。</span></td>
                      </tr>
                      <tr>
                        <td>源端口：&nbsp;&nbsp;</td>
                        <td><input name="sourceport" type="text" class="formfld unknown" id="sourceport" size="5" value="<?=htmlspecialchars($pconfig['sourceport']);?>"> （留空表示所有端口）</td>
                      </tr>
                    </table></td>
                </tr>
                <tr>
                  <td width="22%" valign="top" class="vncellreq">目的地址</td>
                  <td width="78%" class="vtable">
<input name="destination_not" type="checkbox" id="destination_not" value="yes" <?php if ($pconfig['destination_not']) echo "checked"; ?>>
                    <strong>取反</strong><br>
                    <br>
                    <table border="0" cellspacing="1" cellpadding="1">
                      <tr>
                        <td>类型：&nbsp;&nbsp;</td>
                        <td><select name="destination_type" class="formselect" onChange="typesel_change()">
                            <option value="any"<?php if ($pconfig['destination'] == "any") echo " selected"; ?>>
                                所有</option>
                            <option value="network"<?php if ($pconfig['destination'] != "any") echo " selected"; ?>>
                                网段</option>
                          </select></td>
                      </tr>
                      <tr>
                        <td>地址：&nbsp;&nbsp;</td>
                        <td><input name="destination" type="text" class="formfld unknown" id="destination" size="20" value="<?=htmlspecialchars($pconfig['destination']);?>">
                          /
                          <select name="destination_subnet" class="formselect" id="destination_subnet">
<?php for ($i = 32; $i >= 0; $i--): ?>
                            <option value="<?=$i;?>"<?php if ($i == $pconfig['destination_subnet']) echo " selected"; ?>><?=$i;?></option>
<?php endfor; ?>
                          </select> </td>
                      </tr>
                      <tr>
                        <td>&nbsp;</td>
                        <td><span class="vexpl">输入NAT转换的目的地址。</span></td>
                      </tr>
                      <tr>
                        <td>目的端口：&nbsp;&nbsp;</td>
                        <td><input name="dstport" type="text" class="formfld unknown" id="dstport" size="5" value="<?=htmlspecialchars($pconfig['dstport']);?>"> （留空表示所有端口）</td>
                      </tr>
                    </table>
		  </td>
                </tr>
                <tr>
                  <td width="22%" valign="top" class="vncell">转换地址</td>
                  <td width="78%" class="vtable">
			<table border="0" cellspacing="1" cellpadding="1">
			<tr>
			  <td>地址：&nbsp;&nbsp;</td>
			  <td><select name="target" class="formselect">
				<option value=""<?php if (!$pconfig['target']) echo " selected"; ?>>接口地址</option>
<?php	if (is_array($config['virtualip']['vip'])):
		foreach ($config['virtualip']['vip'] as $sn): ?>
				<option value="<?=$sn['subnet'];?>" <?php if ($sn['subnet'] == $pconfig['target']) echo "selected"; ?>><?=htmlspecialchars("{$sn['subnet']} ({$sn['descr']})");?></option>
<?php 		endforeach;
	endif;
?>
				<option value=""<?php if($pconfig['target'] == "any") echo " selected"; ?>>任意</option>
			  </select>
			  </td>
			</tr>
			<tr><td>&nbsp;</td><td>
                     <span class="vexpl">符合该规则的数据包会被转换成该地址。<br>
			如果希望使用其他的IP地址，您需要首先在<a href="firewall_virtual_ip.php">虚拟IP</a>中增加IP地址。
			</span>
			</td></tr>
			<tr>
                          <td>端口：&nbsp;&nbsp;</td>
                          <td><input name="natport" type="text" class="formfld unknown" id="natport" size="5" value="<?=htmlspecialchars($pconfig['natport']);?>"></td>
			</tr>
			<tr><td>&nbsp;</td><td>
                        <span class="vexpl">输入NAT转换的源端口。</span>
			</td></tr>
                        <tr>
                          <td>静态端口：&nbsp;&nbsp;</td>
                          <td><input onChange="staticportchange();" name="staticnatport" type="checkbox" class="formfld" id="staticnatport" size="5"<?php if($pconfig['staticnatport']) echo " CHECKED";?>></td>
			</tr>
			</table>
		  </td>
                </tr>
                <tr>
                  <td width="22%" valign="top" class="vncell">描述</td>
                  <td width="78%" class="vtable">
                    <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
                    <br> <span class="vexpl">您可以输入一些描述作为参考。</span></td>
          </tr>
                <tr>
                  <td width="22%" valign="top">&nbsp;</td>
                  <td width="78%">
                    <input name="Submit" type="submit" class="formbtn" value="保存"> <input type="button" class="formbtn" value="取消" onclick="history.back()">
                    <?php if (isset($id) && $a_out[$id]): ?>
                    <input name="id" type="hidden" value="<?=$id;?>">
                    <?php endif; ?>
                  </td>
                </tr>
              </table>
</form>
<script language="JavaScript">
<!--
typesel_change();
staticportchange();
//-->
</script>
<?php include("fend.inc"); ?>
</body>
</html>
